#include <iostream>
#include <string>
#include <vector>
#include "Character.hh"
#include "Enemy.hh"
#include "Item.hh"
#include "Room.hh"
#include "Player.hh"
#include "Store.hh"
#include <conio.h>
#include <limits>
#include "Goblin.hh"
#include "Troll.hh"
#include "Dragon.hh"
using namespace std;

/*This code implements the main game loop for a text-based adventure game. Key features include:

Game Initialization:
Sets up the game world by calling createGameWorld(currentRoom).
Initializes a player (Player player("Hero")) and a buffer character (Player buff("buff")).
Initializes a static store (Store gameStore).
Game Loop:
Runs continuously until gameRunning is set to false.
Clears the screen and displays the current room's contents and player status.
Combines player attributes using Player splayer = player + buff; (assumes a + operator is defined for Player).
Menu Display and Input Handling:
Displays available options using displayMenu().
Prompts the player for input and validates it, ensuring it's a number.
Processes the player's choice:
Movement: Allows movement between rooms if no enemies are present.
Item Interaction: Lets the player take items if no enemies are present.
Combat: Allows the player to attack enemies, with a chance to receive a dropped item upon victory.
Skill Use: Lets the player use a skill (combined player attributes) to attack enemies, with potential item drops.
Inventory Management: Allows the player to view, use, or sell items in their inventory.
Stats View: Displays the player's current stats.
Store Access: Lets the player view and purchase items from the store.
Combat and Item Drops:
When defeating an enemy, the player gains experience and money.
There's a 30% chance for a dropped item, randomly selected from the store's inventory.
Game End Condition:
The game ends when the player defeats the dragon in the "Dragon Throne" room or is defeated by an enemy.
This code provides a comprehensive game loop that handles player movement, combat, inventory management, and store interactions, offering a rich gameplay experience.*/

void waitForSpace() {
    std::cout << "Pause to continue....." << std::endl;
    int ch;
    do {
        ch = _getch(); 
    } while(ch != 32); 
}


void createGameWorld(Room*& startRoom) {
    Room* chamber = new Room("Starting Chamber");
    Room* corridor = new Room("Narrow Corridor");
    Room* armory = new Room("Armory");
    Room* throne = new Room("Dragon Throne");

    chamber->east = corridor;
    corridor->west = chamber;
    corridor->east = armory;
    armory->west = corridor;
    armory->north = throne;
    throne->south = armory;

    chamber->addItem(new Item("Health Potion", "Restores 10 HP", 10, 10, 0, 0,0));
    armory->addItem(new Item("Iron Sword", "Increases attack by 3", 30, 0, 3, 0,0));
    armory->addItem(new Item("Shield", "Increases defense by 3", 20, 0, 0, 3,0));

    corridor->addEnemy(new Goblin());
    corridor->addEnemy(new Goblin());
    corridor->addEnemy(new Goblin());

    armory->addEnemy(new Troll());
    armory->addEnemy(new Goblin());
    armory->addEnemy(new Goblin());
    
    throne->addEnemy(new Dragon());
    throne->addEnemy(new Goblin());
    throne->addEnemy(new Goblin());
    
    

    startRoom = chamber;
}

void displayMenu(const Room& currentRoom, Player& player, vector<string>& options) {
    options.clear();
    int optionCount = 1;

    if (currentRoom.north) {
        options.push_back("Move north");
        cout << optionCount++ << ". Move north" << endl;
    }
    if (currentRoom.south) {
        options.push_back("Move south");
        cout << optionCount++ << ". Move south" << endl;
    }
    if (currentRoom.east) {
        options.push_back("Move east");
        cout << optionCount++ << ". Move east" << endl;
    }
    if (currentRoom.west) {
        options.push_back("Move west");
        cout << optionCount++ << ". Move west" << endl;
    }

    if (!currentRoom.getItems().empty()) {
        options.push_back("Take item");
        cout << optionCount++ << ". Take item" << endl;
    }

    if (!currentRoom.getEnemies().empty()) {
        options.push_back("Attack enemy");
        cout << optionCount++ << ". Attack enemy" << endl;
    }
    if (player.getskill()){
        options.push_back("Use skill");
        cout<<optionCount++<<". Use skill"<<endl;

    }
    options.push_back("View inventory");
    cout << optionCount++ << ". View inventory" << endl;

    options.push_back("View stats");
    cout << optionCount++ << ". View stats" << endl;

    options.push_back("Store");
    cout << optionCount++ << ". Store" << endl;


    cout << "\nYour HP: " << player.getHealth() << "/" 
         << player.getmaxHealth() << "\n";
}

int main() {
    Room* currentRoom = nullptr;
    createGameWorld(currentRoom);
    Player player("Hero");
    Player buff("buff");
    static Store gameStore;
    bool gameRunning = true;

    while (gameRunning) {
        system("cls");
        currentRoom->displayContents();
        player.display();
        Player splayer=player+buff;

        vector<string> options;
        displayMenu(*currentRoom, player, options); 
        
        int choice;
        while (true) {
            cout << "Enter choice: ";
            if (cin >> choice) {
                
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                break; 
            } else {
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                cout << "Invalid choice! Please enter a number.\n";
            }
        }

        if (choice < 1 || choice > static_cast<int>(options.size())) {
            cout << "Invalid choice! Options are 1-" << options.size() << ".\n";
            waitForSpace();
            continue; 
        }

        const string& selectedOption = options[choice - 1];
            
            if (selectedOption == "Move north" && currentRoom->north) {
                if(!currentRoom->getEnemies().empty()){
                    cout<<"You have to clear the enemies before you go to next place!!!"<<endl;
                    waitForSpace(); 
                }else{
                    currentRoom = currentRoom->north;
                    waitForSpace(); 
                }
                
            } else if (selectedOption == "Move south" && currentRoom->south) {
                if(!currentRoom->getEnemies().empty()){
                    cout<<"You have to clear the enemies before you go to next place!!!"<<endl;
                    waitForSpace(); 
                }else{
                    currentRoom = currentRoom->south;
                    waitForSpace(); 
            }
            } else if (selectedOption == "Move east" && currentRoom->east) {
                if(!currentRoom->getEnemies().empty()){
                    cout<<"You have to clear the enemies before you go to next place!!!"<<endl;
                    waitForSpace(); 
                }else{
                    currentRoom = currentRoom->east;
                    waitForSpace();
            }
            } else if (selectedOption == "Move west" && currentRoom->west) {
                if(!currentRoom->getEnemies().empty()){
                    cout<<"You have to clear the enemies before you go to next place!!!"<<endl;
                    waitForSpace(); 
                }else{
                    currentRoom = currentRoom->west;
                    waitForSpace();
                }
            } else if (selectedOption == "Take item" && !currentRoom->getItems().empty()) {
                if(!currentRoom->getEnemies().empty()){
                    cout<<"You have to clear the enemies before you pick up item!!!!"<<endl;
                    waitForSpace(); 
                }else{
                    for (auto it = currentRoom->getItems().begin(); it != currentRoom->getItems().end();) {
                        Item* item = *it;
                        player.addItemToInventory(item);
                        it = currentRoom->getItems().erase(it);
                    }
                    cout << "Now you can find them in your bag." << endl;
                    waitForSpace(); 
            }
            } else if (selectedOption == "Attack enemy" && !currentRoom->getEnemies().empty()) {
                Character* enemy = currentRoom->getEnemies().back();
                if (player.isAlive()) {
                    
                        player.attack(*enemy);
                        player.manaup();
                        enemy->attack(player); 
                        cout << enemy->toString(); 
                        if (!enemy->isAlive()){
                            int dropChance = 30; 
                            if (rand() % 100 < dropChance) {
                                std::vector<Item*>& storeItems = gameStore.getItemsForSale();
                                if (!storeItems.empty()) {
                                    int randomIndex = rand() % storeItems.size();
                                    Item* selectedItem = storeItems[randomIndex];
                                    Item* droppedItem = new Item(*selectedItem); 
                                    player.addItemToInventory(droppedItem); 
                                    cout << "You found a " << selectedItem->getName() << " dropped from the enemy!\n";
                                }
                            }
                            currentRoom->getEnemies().pop_back();
                            delete enemy;
                            cout << "Enemy defeated!\n";
                            player.gainExperience(50); 
                            player.gainMoney(enemy->getMoney());
                            if (currentRoom->description == "Dragon Throne" && currentRoom->getEnemies().empty()) {
                                cout << "Congratulations! You defeated the dragon!\n";
                                gameRunning = false;
                            }
                        
                    }
                }
                else{
                    cout << "You were defeated!\n";
                    gameRunning = false;
                }
                waitForSpace();
            }else if(selectedOption =="Use skill"){
                Character* enemy = currentRoom->getEnemies().back();
                if (player.isAlive()) {
                        Player splayer=player+splayer;
                        splayer.attack(*enemy);
                        cout << enemy->toString();
                        player.skillreset(); 
                        if (!enemy->isAlive()){
                            int dropChance = 30; 
                            if (rand() % 100 < dropChance) {
                                std::vector<Item*>& storeItems = gameStore.getItemsForSale();
                                if (!storeItems.empty()) {
                                    int randomIndex = rand() % storeItems.size();
                                    Item* selectedItem = storeItems[randomIndex];
                                    Item* droppedItem = new Item(*selectedItem); 
                                    player.addItemToInventory(droppedItem); 
                                    cout << "You found a " << selectedItem->getName() << " dropped from the enemy!\n";
                                }
                            }
                            currentRoom->getEnemies().pop_back();
                            delete enemy;
                            cout << "Enemy defeated!\n";
                            player.gainExperience(50); 
                            player.gainMoney(enemy->getMoney());
                            if (currentRoom->description == "Dragon Throne" && currentRoom->getEnemies().empty()) {
                                cout << "Congratulations! You defeated the dragon!\n";
                                gameRunning = false;
                            }
                            
                        }
                }
                else{
                    cout << "You were defeated!\n";
                    gameRunning = false;
                }

                waitForSpace();

            }
            else if (selectedOption == "View inventory") {
                player.displayInventory();
                
                bool isInventoryEmpty = player.inventory.empty();
                if (isInventoryEmpty) {
                    cout << "Inventory is empty. Press 0 to exit.\n";
                }
                
                while (true) {
                    cout << "Enter the number of the item you want to use or sell (or 0 to exit): ";
                    
                    int itemChoice; 
                    if (cin >> itemChoice) {
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    } else {
                        cin.clear();
                        cin.ignore(numeric_limits<streamsize>::max(), '\n');
                        cout << "Error: Invalid input. Please enter a number.\n";
                        continue; 
                    }
                    
                    if (itemChoice == 0) {
                        break;
                    }
                    
                    if (isInventoryEmpty) {
                        cout << "Error: Inventory is empty. Press 0 to exit.\n";
                        continue;
                    } else {
                        int maxItem = player.inventory.size();
                        if (itemChoice < 1 || itemChoice > maxItem) {
                            cout << "Error: Invalid item number. Valid options: 1-" << maxItem << ".\n";
                            continue;
                        }
                        
                        Item* selectedItem = player.inventory[itemChoice - 1];
                        cout << "Press 1 to use or press 2 to sell" << endl;
                        int cc;
                        cin >> cc; 
                        
                        if(cc == 1){
                            if (player.useItem(selectedItem)) {
                                cout << "Item used.\n";
                            } else {
                                cout << "Failed to use item.\n";
                            }
                        } else if(cc == 2){
                            if (player.soldItem(selectedItem)) {
                                cout << "Item sold.\n";
                            } else {
                                cout << "Failed to sell item.\n";
                            }
                        } else {
                            cout << "Invalid choice. No action taken.\n";
                        }
                        break;
                    }
                }
                
                waitForSpace(); 
            }else if (selectedOption == "View stats") {
                cout << player.toString();
                waitForSpace(); 
            } else if (selectedOption == "Store") {
                
                while(true) {
                    system("cls"); 
                    gameStore.displayItems();
                    cout << "\nYour Money: " << player.getMoney() << endl;
                    cout << "Enter the number of the item you want to buy (or 0 to exit): ";
                    int storeChoice;
                    cin >> storeChoice;
                    cin.ignore();
                    if(storeChoice == 0) break; 
                    if(gameStore.buyItem(player, storeChoice - 1)) { 
                        cout << "You bought a " << gameStore.getItemsForSale()[storeChoice - 1]->getName() << "." << endl;
                    }
                    waitForSpace();
                }
            }
        
    }

   
    Room* roomToDelete = currentRoom;
    while (roomToDelete != nullptr) {
        Room* nextRoom = roomToDelete->east ? roomToDelete->east : 
                         roomToDelete->south ? roomToDelete->south : 
                         roomToDelete->west ? roomToDelete->west : 
                         roomToDelete->north ? roomToDelete->north : nullptr;

        for (Character* enemy : roomToDelete->getEnemies()) {
            delete enemy;
        }

        delete roomToDelete;
        roomToDelete = nextRoom;
    }

    return 0;
}